﻿using System;

namespace Core.Tools
{
    /// <summary> 提供对象与指针的工具函数 </summary>
    public static unsafe class InternalPointer
    {
        /// <summary> 将指针装箱成对象 </summary>
        public static object Box(void* LpObject)
        {
            object Result = null;

            TypedReference ObjectRef = __makeref(Result);

            **(void***)(&ObjectRef) = LpObject;

            return Result;
        }
        /// <summary> 将对象拆箱为指针 </summary>
        public static void* UnBox(object Object)
        {
            TypedReference ObjectRef = __makeref(Object);

            return **(void***)(&ObjectRef);
        }
        /// <summary> 将指针封装成对象 </summary>
        public static object SafeBox(IntPtr LpObject)
        {
            return Box((void*)LpObject);
        }
        /// <summary> 将对象拆箱为指针 </summary>
        public static IntPtr SafeUnBox(object Object)
        {
            return (IntPtr)UnBox(Object);
        }


        /// <summary> 更改对象的类型，对该对象的所有引用都生效：转换之前请确保两个类型兼容 </summary>
        public static T Cast<T>(object Object)
        {
            return (T)Cast(Object, (void*)typeof(T).TypeHandle.Value);
        }
        /// <summary> 将指针装箱成对象并更改该对象的类型，对该对象的所有引用都生效：转换之前请确保两个类型兼容 </summary>
        public static T Cast<T>(void* LpObject)
        {
            return (T)Cast(LpObject, (void*)typeof(T).TypeHandle.Value);
        }
        /// <summary> 更改对象的类型，对该对象的所有引用都生效：转换之前请确保两个类型兼容 </summary>
        public static object Cast(object Object, Type Type)
        {
            return Cast(Object, (void*)Type.TypeHandle.Value);
        }
        /// <summary> 将指针装箱成对象并更改该对象的类型，对该对象的所有引用都生效：转换之前请确保两个类型兼容 </summary>
        public static object Cast(void* LpObject, Type Type)
        {
            return Cast(LpObject, (void*)Type.TypeHandle.Value);
        }
        /// <summary> 更改对象的类型，对该对象的所有引用都生效：转换之前请确保两个类型兼容 </summary>
        public static object Cast(object Object, IntPtr TypeHandle)
        {
            return Cast(Object, (void*)TypeHandle);
        }
        /// <summary> 将指针装箱成对象并更改该对象的类型，对该对象的所有引用都生效：转换之前请确保两个类型兼容 </summary>
        public static object Cast(void* LpObject, IntPtr TypeHandle)
        {
            return Cast(LpObject, (void*)TypeHandle);
        }
        /// <summary> 更改对象的类型，对该对象的所有引用都生效：转换之前请确保两个类型兼容 </summary>
        public static object Cast(object Object, void* TypeHandle)
        {
            *(void**)UnBox(Object) = TypeHandle;

            return Object;
        }
        /// <summary> 将指针装箱成对象并更改该对象的类型，对该对象的所有引用都生效：转换之前请确保两个类型兼容 </summary>
        public static object Cast(void* LpObject, void* TypeHandle)
        {
            *(void**)LpObject = TypeHandle;

            return Box(LpObject);
        }
        /// <summary> 将指针装箱成对象并更改该对象的类型，对该对象的所有引用都生效：转换之前请确保两个类型兼容 </summary>
        public static T SafeCast<T>(IntPtr LpObject)
        {
            return (T)Cast((void*)LpObject, (void*)typeof(T).TypeHandle.Value);
        }
        /// <summary> 将指针装箱成对象并更改该对象的类型，对该对象的所有引用都生效：转换之前请确保两个类型兼容 </summary>
        public static object SafeCast(IntPtr LpObject, Type Type)
        {
            return Cast((void*)LpObject, (void*)Type.TypeHandle.Value);
        }

        /// <summary> 获得 TypeHandle </summary>
        public static IntPtr GetTypeHandle(void* LpObject)
        {
            return *(IntPtr*)LpObject;
        }
        /// <summary> 获得 TypeHandle </summary>
        public static IntPtr GetTypeHandle(object Object)
        {
            return Object.GetType().TypeHandle.Value;
        }
        /// <summary> 获得 TypeHandle </summary>
        public static IntPtr SafeGetTypeHandle(IntPtr LpObject)
        {
            return *(IntPtr*)LpObject;
        }
    }
}